#define GPR_LAYOUT		\
	GPR_OFFSET ($s0, 0);	\
	GPR_OFFSET ($s1, 1);	\
	GPR_OFFSET ($s2, 2);	\
	GPR_OFFSET ($s3, 3);	\
	GPR_OFFSET ($s4, 4);	\
	GPR_OFFSET ($s5, 5);	\
	GPR_OFFSET ($s6, 6);	\
	GPR_OFFSET ($s7, 7);	\
	GPR_OFFSET ($s8, 8);	\
	GPR_OFFSET ($ra, 9);	\
	GPR_OFFSET ($sp, 10);   \
	GPR_OFFSET ($fp, 11);

#define NUM_GPRS_SAVED 12

#if __loongarch_single_float == 1 || __loongarch_double_float == 1
#define FPR_LAYOUT		\
	FPR_OFFSET ($f24, 0);	\
	FPR_OFFSET ($f25, 1);	\
	FPR_OFFSET ($f26, 2);	\
	FPR_OFFSET ($f27, 3);	\
	FPR_OFFSET ($f28, 4);	\
	FPR_OFFSET ($f29, 5);	\
	FPR_OFFSET ($f30, 6);	\
	FPR_OFFSET ($f31, 7);
#else
#define FPR_LAYOUT 
#endif

#define LOAD_GPR ld.w
#define STORE_GPR st.w
#define BYTES_PER_WORD 4

#if __loongarch_double_float == 1
#define LOAD_FPR fld.d
#define STORE_FPR fst.d
#else
#define LOAD_FPR fld.s
#define STORE_FPR fst.s
#endif

#define GPOFF(INDEX) (INDEX * BYTES_PER_WORD)
#define FPOFF(INDEX) ((INDEX + NUM_GPRS_SAVED) * BYTES_PER_WORD)

/* int setjmp (jmp_buf);  */
	.globl	setjmp
setjmp:

#define GPR_OFFSET(REG, INDEX) STORE_GPR REG,$r4,GPOFF(INDEX)
#define FPR_OFFSET(REG, INDEX) STORE_FPR REG,$r4,FPOFF(INDEX)
	GPR_LAYOUT
	FPR_LAYOUT
#undef GPR_OFFSET
#undef FPR_OFFSET

	or	$r4,$r0,$r0
	jirl	$r0,$r1,0


/* volatile void longjmp (jmp_buf, int);  */
	.globl	longjmp
longjmp:

#define GPR_OFFSET(REG, INDEX) LOAD_GPR REG,$r4,GPOFF(INDEX)
#define FPR_OFFSET(REG, INDEX) LOAD_FPR REG,$r4,FPOFF(INDEX)
	GPR_LAYOUT
	FPR_LAYOUT
#undef GPR_OFFSET
#undef FPR_OFFSET

	bne	$r5,$r0,1f
	li.w	$r5,1
1:
	or	$r4,$r5,$r0
	jirl	$r0,$r1,0

